home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swags_z.zip / TEXTFILE.SWG / 0027_Reading File Backwards.pas < prev    next >
Pascal/Delphi Source File  |  1993-11-26  |  4KB  |  184 lines

  1. {
  2.    Fast driver for backwards reading...  Aha!
  3.    This is the way to do it.
  4.  
  5.    Below you will find the source of a "tail" program.
  6.    I wrote it because I needed to check the status of some log files,
  7.    and I didn't want to go through the entire file every time, as the
  8.    files could grow quite large.
  9.  
  10.    It is currently limited to 255 chars per line, but that
  11.    can easily be fixed (see the Limit const).
  12.  
  13.    Although it's not an exact solution to your problem, it will show you
  14.    how to do "backwards" reading.
  15. }
  16.  
  17. PROGRAM Tail;
  18. {
  19.   Shows the tailing lines of a text file.
  20.  
  21.   Syntax: TAIL [d:\path]filespec.ext [-<lines>]
  22.           Default number of lines is 10.
  23.  
  24.           "TAIL filename -20" will show the 20 last lines
  25.  
  26.   Written by Lars Fosdal, 1993 
  27.   Released to the Public Domain by Lars Fosdal, 1993
  28. }
  29.  
  30. USES
  31.   DOS, Objects, Strings;
  32.  
  33. CONST
  34.   MaxBufSize = 32000;
  35. TYPE
  36.   pBuffer = ^TBuffer;
  37.   TBuffer = ARRAY[0..MaxBufSize-1] OF Char;
  38.  
  39.   pRawStrCollection = ^TRawStrCollection;
  40.   TRawStrCollection = OBJECT(TCollection)
  41.     PROCEDURE FreeItem(Item:Pointer); VIRTUAL;
  42.   END;
  43.   
  44. PROCEDURE TRawStrCollection.FreeItem(Item:Pointer);
  45. BEGIN
  46.   IF Item<>nil
  47.   THEN StrDispose(pChar(Item));
  48. END; {PROC TRawStrCollection.FreeItem}
  49.  
  50. FUNCTION ShowTail(FileName:String; n:Integer):Integer;
  51.   PROCEDURE DumpLine(p:pChar); FAR;
  52.   BEGIN
  53.     IF p^=#255
  54.     THEN Writeln
  55.     ELSE Writeln(p);
  56.   END;
  57. CONST
  58.   Limit = 255;  
  59. VAR
  60.   lines   : pRawStrCollection;
  61.   fm      : Byte;
  62.   f       : File;
  63.   fs,fp   : LongInt;
  64.   MaxRead : Word;
  65.   Buf     : pBuffer;
  66.   lc,ix,ex : Integer;
  67.   sp      : ARRAY[0..Limit] OF Char;
  68. BEGIN
  69.   lines:=nil;
  70.   fm:=FileMode;
  71.   FileMode:=$40; {Read-only, deny none}
  72.   Assign(f, FileName);
  73.   Reset(f, 1);
  74.   lc:=IOResult;
  75.   IF lc=0
  76.   THEN BEGIN
  77.     New(Buf);
  78.    
  79.     fs:=FileSize(f); {First, let's find out how much to read}
  80.     fp:=fs-MaxBufSize;
  81.     IF fp<0
  82.     THEN fp:=0;
  83.     
  84.     Seek(f,fp); {Then, read it}
  85.     BlockRead(f, Buf^, MaxBufSize, MaxRead);
  86.     Close(f);
  87.     
  88.     IF MaxRead>0
  89.     THEN BEGIN
  90.       New(Lines, Init(n,10));
  91.       ix:=MaxRead-1;
  92.  
  93.       IF Buf^[ix]=^J THEN Dec(ix);
  94.       IF (ix>0) and (Buf^[ix]=^M) THEN Dec(ix); {Skip trailing line break}
  95.  
  96.       WHILE (lc<n) and (ix>0)
  97.       DO BEGIN
  98.         ex:=ix;
  99.         FillChar(sp, SizeOf(sp), 0);
  100.         
  101.         WHILE (ix>0) and not (Buf^[ix] =^J)
  102.         DO Dec(ix);
  103.         
  104.         IF ex-ix<=Limit {If no break was found within limit, it's no txt file}
  105.         THEN BEGIN
  106.           IF ix=ex
  107.           THEN sp[0]:=#255 {Pad empty lines to avoid zero-length pchar}
  108.           ELSE StrLCopy(sp, @Buf^[ix+1], ex-ix);
  109.           Inc(lc);
  110.  
  111.           Lines^.AtInsert(0, StrNew(sp));
  112.  
  113.           Dec(ix);
  114.           WHILE (ix>0) and (Buf^[ix] =^M)
  115.           DO Dec(ix);
  116.         END
  117.         ELSE BEGIN
  118.           Writeln('"',FileName,'" doesn''t seem to be a text file');
  119.           ix:=-1;
  120.         END;
  121.  
  122.       END; {lc<n and ix>0}
  123.     END {Maxread>0}
  124.     ELSE Lines:=nil;
  125.     Dispose(Buf);
  126.   END
  127.   ELSE lc:=-lc;
  128.  
  129.   IF Lines<>nil
  130.   THEN BEGIN
  131.     Lines^.ForEach(@DumpLine);
  132.     Dispose(Lines, Done);
  133.   END;
  134.  
  135.   ShowTail:=lc;
  136.   FileMode:=fm;
  137. END; {FUNC ShowTail}
  138.  
  139. TYPE
  140.   CharSet = Set of Char;
  141.  
  142. FUNCTION StripAll(CONST Exclude:CharSet; S:String):String;
  143. VAR
  144.   ix : Integer;
  145. BEGIN
  146.   ix:=Length(S);
  147.   WHILE ix>0
  148.   DO BEGIN
  149.     IF S[ix] in Exclude
  150.     THEN Delete(S, ix, 1);
  151.     Dec(ix);
  152.   END;
  153.   StripAll:=S;
  154. END; {FUNC StripAll}  
  155.   
  156. VAR
  157.   r : Integer;
  158.   l : Integer;
  159.   e : Integer;
  160. BEGIN
  161.   IF (ParamCount<1) or (ParamCount>2)
  162.   THEN BEGIN
  163.     Writeln('TAIL v.1.0 - PD 1993 Lars Fosdal');
  164.     Writeln('  TAIL [d:\path]filename.ext [-n]');
  165.     Writeln('  Default is 10 lines');
  166.   END
  167.   ELSE BEGIN
  168.     IF ParamCount=2
  169.     THEN BEGIN
  170.       Val(StripAll(['/','-'], ParamStr(2)), l, e);
  171.       IF e<>0
  172.       THEN l:=10
  173.     END
  174.     ELSE l:=10;
  175.  
  176.     r:=ShowTail(ParamStr(1), l);
  177.     IF r<0
  178.     THEN BEGIN
  179.       Writeln('Couldn''t open "',ParamStr(1),'"!  (Error ', -r,')');
  180.       Halt(Word(-r));
  181.     END;
  182.   END;
  183. END.
  184.